﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using Framework.Data;
using System.Linq.Expressions;
using Framework.Common.LinqExtention;
using Framework.Common;
using System.Data.Entity.Validation;
using System.Data.Entity.Infrastructure;
using System.Data;
using System.Data.Common;
using System.Globalization;
namespace Framework.Data.Implement
{
    /// <summary>
    /// 不需要整洁只需要高效
    /// </summary>
    public class GenericRepository : IRepository
    {
        #region private member
        private DbContext _context;
        private IUnitOfWork unitOfWork;
        #endregion

        #region constructor
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public GenericRepository(DbContext context)
        {
            _context = context;
        }
        #endregion

        #region getQuery
        /// <summary>
        /// 获取查询对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public IQueryable<T> GetQuery<T>(Expression<Func<T, bool>> where = null) where T : class
        {
            return where == null ? DbContext.Set<T>().AsNoTracking() : DbContext.Set<T>().Where(where).AsNoTracking();
        }
        #endregion

        #region 适用于单表操作的

        #region 添加
        /// <summary>
        /// 添加
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        public void Add<T>(T entity) where T : class
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            DbContext.Set<T>().Add(entity);
        }

        /// <summary>
        /// 添加
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        public int AddThenSaveChange<T>(T entity) where T : class
        {
            Add(entity);
            return Save();
        }
        #endregion

        #region 更新

        #region  更新单条
        /// <summary>
        /// 附加对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        public void Attach<T>(T entity, Action<T> action = null) where T : class
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity cannot be null");
            }
            DbContext.Set<T>().Attach(entity);
            if (action != null)
            {
                action(entity);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <param name="action"></param>
        /// <returns></returns>
        public int AttachThenSaveChange<T>(T entity, Action<T> action = null) where T : class
        {
            Attach(entity, action);
            return Save();
        }
        #endregion

        #endregion

        #region 删除

        #region 删除单条
        /*
         * 注意并发值和外键
         Product stub = new Product {
                ID = 3,
                Category = new Category { ID = 1 }
         };
         ctx.AttachTo("Products", stub);
         */
        /// <summary>
        /// 删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        public void Delete<T>(T entity) where T : class
        {
            if (entity == null)
            {
                throw new ArgumentNullException("entity");
            }
            var dbset = DbContext.Set<T>();
            dbset.Attach(entity);
            dbset.Remove(entity);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="entity"></param>
        /// <returns></returns>
        public int DeleteThenSaveChange<T>(T entity) where T : class
        {
            Delete(entity);
            return Save();
        }
        #endregion

        #endregion

        #region 获取数量
        /// <summary>
        /// 获取数量
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="criteria"></param>
        /// <returns></returns>
        public int Count<T>() where T : class
        {
            return GetQuery<T>().Count();
        }

        /// <summary>
        /// 获取数量
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public int Count<T>(Expression<Func<T, bool>> where) where T : class
        {
            return GetQuery<T>(where).Count();
        }
        #endregion

        #region 查询返回单条数据

        #region 获取符合条件的第一条
        /// <summary>
        /// 获取符合条件的第一条
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public T First<T>() where T : class
        {
            return GetQuery<T>().FirstOrDefault();
        }

        /// <summary>
        /// 排序后第一条(仅支持一个属性的排序)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public T First<T, TKey>(Expression<Func<T, TKey>> orderBy, bool desc = false) where T : class
        {
            return desc ? GetQuery<T>().OrderByDescending(orderBy).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).FirstOrDefault();
        }

        /// <summary>
        /// 获取符合条件的第一条
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="predicate"></param>
        /// <returns></returns>
        public T First<T>(Expression<Func<T, object>> select) where T : class
        {
            var obj = GetQuery<T>().Select(select).FirstOrDefault();
            return obj.CastTo<T>();
        }

        /// <summary>
        /// 获取符合条件的第一条
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TKey">排序的属性</typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public T First<T, TKey>(Expression<Func<T, object>> select, Expression<Func<T, TKey>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ? GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj.CastTo<T>();
        }

        /// <summary>
        /// 获取符合条件的第一条
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public T First<T>(Expression<Func<T, bool>> where) where T : class
        {
            return GetQuery<T>(where).FirstOrDefault();
        }

        /// <summary>
        /// 获取符合条件的第一条
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public T First<T, TKey>(Expression<Func<T, bool>> where, Expression<Func<T, TKey>> orderBy, bool desc = false) where T : class
        {
            return desc ? GetQuery<T>(where).OrderByDescending(orderBy).FirstOrDefault() :
               GetQuery<T>(where).OrderBy(orderBy).FirstOrDefault();
        }

        /// <summary>
        /// 获取符合条件的第一条
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public T First<T>(Expression<Func<T, bool>> where, Expression<Func<T, object>> select) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj.CastTo<T>();
        }

        /// <summary>
        /// 获取符合条件的第一条
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public T First<T, TKey>(Expression<Func<T, bool>> where, Expression<Func<T, object>> select, Expression<Func<T, TKey>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj.CastTo<T>();
        }
        #endregion

        #region 获取符合条件的第一条 (返回基本类型)

        /// <summary>
        /// 返回基本类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public TResult FirstPrimitives<T, TResult>(Func<T, TResult> select) where T : class
        {
            return GetQuery<T>().Select(select).FirstOrDefault();
        }


        /// <summary>
        /// 返回基本类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <typeparam name="TOrderByProperty"></typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public TResult FirstPrimitives<T, TResult, TOrderByProperty>(Expression<Func<T, TResult>> select, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 获取符合条件的第一条
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public TResult FirstPrimitives<T, TResult>(Expression<Func<T, TResult>> select, Expression<Func<T, bool>> where) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 获取符合条件的第一条
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public TResult FirstPrimitives<T, TResult, TOrderByProperty>(Expression<Func<T, TResult>> select, Expression<Func<T, bool>> where, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }
        #endregion

        //基本类型

        #region 获取符合条件的第一条 (返回int类型)

        /// <summary>
        /// 返回int类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public int FirstInt<T>(Func<T, int> select) where T : class
        {
            return GetQuery<T>().Select(select).FirstOrDefault();
        }

        /// <summary>
        /// 返回int类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TOrderByProperty"></typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public int FirstInt<T, TOrderByProperty>(Expression<Func<T, int>> select, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回int类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public int FirstInt<T>(Expression<Func<T, int>> select, Expression<Func<T, bool>> where) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回int类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public int FirstInt<T, TOrderByProperty>(Expression<Func<T, int>> select, Expression<Func<T, bool>> where, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }
        #endregion

        #region 获取符合条件的第一条 (返回string类型)

        /// <summary>
        /// 返回string类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public string FirstString<T>(Func<T, string> select) where T : class
        {
            return GetQuery<T>().Select(select).FirstOrDefault();
        }

        /// <summary>
        /// 返回string类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TOrderByProperty"></typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public string FirstString<T, TOrderByProperty>(Expression<Func<T, string>> select, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回string类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public string FirstString<T>(Expression<Func<T, string>> select, Expression<Func<T, bool>> where) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回string类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public string FirstString<T, TOrderByProperty>(Expression<Func<T, string>> select, Expression<Func<T, bool>> where, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }
        #endregion

        #region 获取符合条件的第一条 (返回decimal类型)

        /// <summary>
        /// 返回decimal类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public decimal FirstDecimal<T>(Func<T, decimal> select) where T : class
        {
            return GetQuery<T>().Select(select).FirstOrDefault();
        }

        /// <summary>
        /// 返回decimal类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TOrderByProperty"></typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public decimal FirstDecimal<T, TOrderByProperty>(Expression<Func<T, decimal>> select, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回decimal类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public decimal FirstDecimal<T>(Expression<Func<T, decimal>> select, Expression<Func<T, bool>> where) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回decimal类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public decimal FirstDecimal<T, TOrderByProperty>(Expression<Func<T, decimal>> select, Expression<Func<T, bool>> where, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }
        #endregion

        #region 获取符合条件的第一条 (返回double类型)

        /// <summary>
        /// 返回double类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public double FirstDouble<T>(Func<T, double> select) where T : class
        {
            return GetQuery<T>().Select(select).FirstOrDefault();
        }

        /// <summary>
        /// 返回double类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TOrderByProperty"></typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public double FirstDouble<T, TOrderByProperty>(Expression<Func<T, double>> select, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回double类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public double FirstDouble<T>(Expression<Func<T, double>> select, Expression<Func<T, bool>> where) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回double类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public double FirstDouble<T, TOrderByProperty>(Expression<Func<T, double>> select, Expression<Func<T, bool>> where, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }
        #endregion

        #region 获取符合条件的第一条 (返回Boolean类型)

        /// <summary>
        /// 返回Boolean类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public Boolean FirstBoolean<T>(Func<T, Boolean> select) where T : class
        {
            return GetQuery<T>().Select(select).FirstOrDefault();
        }

        /// <summary>
        /// 返回Boolean类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TOrderByProperty"></typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public Boolean FirstBoolean<T, TOrderByProperty>(Expression<Func<T, Boolean>> select, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回Boolean类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public Boolean FirstBoolean<T>(Expression<Func<T, Boolean>> select, Expression<Func<T, bool>> where) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回Boolean类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public Boolean FirstBoolean<T, TOrderByProperty>(Expression<Func<T, Boolean>> select, Expression<Func<T, bool>> where, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }
        #endregion

        //可空类型

        #region 获取符合条件的第一条 (返回 Nullable<int> 类型)

        /// <summary>
        /// 返回int类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public Nullable<int> FirstInt<T>(Func<T, Nullable<int>> select) where T : class
        {
            return GetQuery<T>().Select(select).FirstOrDefault();
        }

        /// <summary>
        /// 返回int类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TOrderByProperty"></typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public Nullable<int> FirstInt<T, TOrderByProperty>(Expression<Func<T, Nullable<int>>> select, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回int类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public Nullable<int> FirstInt<T>(Expression<Func<T, Nullable<int>>> select, Expression<Func<T, bool>> where) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回int类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public Nullable<int> FirstInt<T, TOrderByProperty>(Expression<Func<T, Nullable<int>>> select, Expression<Func<T, bool>> where, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }
        #endregion

        #region 获取符合条件的第一条 (返回Nullable<decimal>类型)

        /// <summary>
        /// 返回decimal类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public Nullable<decimal> FirstDecimal<T>(Func<T, Nullable<decimal>> select) where T : class
        {
            return GetQuery<T>().Select(select).FirstOrDefault();
        }

        /// <summary>
        /// 返回decimal类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TOrderByProperty"></typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public Nullable<decimal> FirstDecimal<T, TOrderByProperty>(Expression<Func<T, Nullable<decimal>>> select, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回decimal类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public Nullable<decimal> FirstDecimal<T>(Expression<Func<T, Nullable<decimal>>> select, Expression<Func<T, bool>> where) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回decimal类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public Nullable<decimal> FirstDecimal<T, TOrderByProperty>(Expression<Func<T, Nullable<decimal>>> select, Expression<Func<T, bool>> where, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }
        #endregion

        #region 获取符合条件的第一条 (返回Nullable<double>类型)

        /// <summary>
        /// 返回double类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public Nullable<double> FirstDouble<T>(Func<T, Nullable<double>> select) where T : class
        {
            return GetQuery<T>().Select(select).FirstOrDefault();
        }

        /// <summary>
        /// 返回double类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TOrderByProperty"></typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public Nullable<double> FirstDouble<T, TOrderByProperty>(Expression<Func<T, Nullable<double>>> select, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回double类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public Nullable<double> FirstDouble<T>(Expression<Func<T, Nullable<double>>> select, Expression<Func<T, bool>> where) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回double类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public Nullable<double> FirstDouble<T, TOrderByProperty>(Expression<Func<T, Nullable<double>>> select, Expression<Func<T, bool>> where, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }
        #endregion

        #region 获取符合条件的第一条 (返回Nullable<Boolean>类型)

        /// <summary>
        /// 返回Boolean类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="func"></param>
        /// <returns></returns>
        public Nullable<Boolean> FirstBoolean<T>(Func<T, Nullable<Boolean>> select) where T : class
        {
            return GetQuery<T>().Select(select).FirstOrDefault();
        }

        /// <summary>
        /// 返回Boolean类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TOrderByProperty"></typeparam>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public Nullable<Boolean> FirstBoolean<T, TOrderByProperty>(Expression<Func<T, Nullable<Boolean>>> select, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>().OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>().OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回Boolean类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public Nullable<Boolean> FirstBoolean<T>(Expression<Func<T, Nullable<Boolean>>> select, Expression<Func<T, bool>> where) where T : class
        {
            var obj = GetQuery<T>(where).Select(select).FirstOrDefault();
            return obj;
        }

        /// <summary>
        /// 返回Boolean类型
        /// </summary>
        /// <param name="where"></param>
        /// <returns></returns>
        public Nullable<Boolean> FirstBoolean<T, TOrderByProperty>(Expression<Func<T, Nullable<Boolean>>> select, Expression<Func<T, bool>> where, Expression<Func<T, TOrderByProperty>> orderBy, bool desc = false) where T : class
        {
            var obj = desc ?
                GetQuery<T>(where).OrderByDescending(orderBy).Select(select).FirstOrDefault() :
                GetQuery<T>(where).OrderBy(orderBy).Select(select).FirstOrDefault();
            return obj;
        }
        #endregion

        #endregion

        #region 获取分页数据并排序(select/where/order)

        /// <summary>
        /// order
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="Tkey"></typeparam>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="recordCount"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public IList<T> GetPaged<T, Tkey>(int pageIndex, int pageSize, out int recordCount, Expression<Func<T, Tkey>> orderBy, bool desc = false) where T : class
        {
            IQueryable<T> query = GetQuery<T>();
            recordCount = query.Count();
            query = desc ? query.OrderByDescending(orderBy) : query.OrderBy(orderBy);
            return query.ToPagedList(pageIndex, pageSize);
        }

        /// <summary>
        /// select/order
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="recordCount"></param>
        /// <param name="select"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public IList<T> GetPaged<T, TKey>(int pageIndex, int pageSize, out int recordCount, Expression<Func<T, Object>> select, Expression<Func<T, TKey>> orderBy, bool desc = false) where T : class
        {
            IQueryable<T> query = GetQuery<T>();
            recordCount = query.Count();
            query = desc ? query.OrderByDescending(orderBy) : query.OrderBy(orderBy);
            return query.Select(select).ToPagedList(pageIndex, pageSize).CastToList<T>();
        }

        /// <summary>
        /// where/order
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="recordCount"></param>
        /// <param name="where"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public IList<T> GetPaged<T, TKey>(int pageIndex, int pageSize, out int recordCount, Expression<Func<T, bool>> where, Expression<Func<T, TKey>> orderBy, bool desc = false) where T : class
        {
            IQueryable<T> query = GetQuery<T>(where);
            recordCount = query.Count();
            query = desc ? query.OrderByDescending(orderBy) : query.OrderBy(orderBy);
            return query.ToPagedList(pageIndex, pageSize);
        }

        /// <summary>
        /// select/where/order
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="Tkey"></typeparam>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="recordCount"></param>
        /// <param name="select"></param>
        /// <param name="where"></param>
        /// <param name="orderBy"></param>
        /// <param name="desc"></param>
        /// <returns></returns>
        public IList<T> GetPaged<T, Tkey>(int pageIndex, int pageSize, out int recordCount, Expression<Func<T, Object>> select, Expression<Func<T, bool>> where, Expression<Func<T, Tkey>> orderBy, bool desc = false) where T : class
        {
            IQueryable<T> query = GetQuery(where);
            recordCount = query.Count();
            query = desc ? query.OrderByDescending(orderBy) : query.OrderBy(orderBy);
            return query.Select(select).ToPagedList(pageIndex, pageSize).CastToList<T>();
        }

        #endregion

        #region 获取单表不分页(获取所有数据的时候不需要排序/内存中排序)

        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public IList<T> Get<T>() where T : class
        {
            return GetQuery<T>().ToList();
        }

        /// <summary>
        /// select expression
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="select"></param>
        /// <returns></returns>
        public IList<T> Get<T>(Expression<Func<T, Object>> select) where T : class
        {
            return GetQuery<T>().Select(select).CastToList<T>();
        }

        /// <summary>
        /// where expression
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public IList<T> Get<T>(Expression<Func<T, bool>> where) where T : class
        {
            return GetQuery<T>(where).ToList();
        }

        /// <summary>
        /// where and select expression
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="where"></param>
        /// <returns></returns>
        public IList<T> Get<T>(Expression<Func<T, bool>> where, Expression<Func<T, Object>> select) where T : class
        {
            return GetQuery<T>(where).Select(select).CastToList<T>();
        }

        #endregion

        #region 获取对象根据主键
        /// <summary>
        /// 获取对象根据主键
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="keyValues"></param>
        /// <returns></returns>
        public T GetByKey<T>(params object[] keyValues) where T : class
        {
            return DbContext.Set<T>().Find(keyValues);
        }
        #endregion

        #endregion

        #region 直接执行sql
        /// <summary>
        /// 直接执行sql
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public IList<T> Get<T>(string sql, params object[] parameters)
        {
            //var connection = DbContext.Database.Connection;
            //if (connection.State != ConnectionState.Open)
            //{
            //    connection.Open();
            //}
            //DbCommand command = CreateStoreCommand(connection, sql, parameters);
            //DbDataReader ddr = command.ExecuteReader(CommandBehavior.Default);
            //while (ddr.Read())
            //{
            //    ddr.get
            //}
            return DbContext.Database.SqlQuery<T>(sql, parameters).ToList();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="connection"></param>
        /// <param name="commandText"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        private DbCommand CreateStoreCommand(DbConnection connection, string commandText, params object[] parameters)
        {
            DbCommand command = connection.CreateCommand();
            command.CommandText = commandText;

            if ((parameters != null) && (parameters.Length > 0))
            {
                DbParameter[] values = new DbParameter[parameters.Length];
                if (parameters.All<object>(p => p is DbParameter))
                {
                    for (int i = 0; i < parameters.Length; i++)
                    {
                        values[i] = (DbParameter)parameters[i];
                    }
                }
                else
                {
                    string[] strArray = new string[parameters.Length];
                    string[] args = new string[parameters.Length];
                    for (int j = 0; j < parameters.Length; j++)
                    {
                        strArray[j] = string.Format(CultureInfo.InvariantCulture, "p{0}", new object[] { j });
                        values[j] = command.CreateParameter();
                        values[j].ParameterName = strArray[j];
                        values[j].Value = parameters[j] ?? DBNull.Value;
                        args[j] = "@" + strArray[j];
                    }
                    command.CommandText = string.Format(CultureInfo.InvariantCulture, command.CommandText, args);
                }
                command.Parameters.AddRange(values);
            }
            return command;
        }






        /// <summary>
        /// 直接执行命令
        /// </summary>
        /// <param name="sql"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        public int ExecuteCommand(string sql, params object[] parameters)
        {
            return DbContext.Database.ExecuteSqlCommand(sql, parameters);
        }
        #endregion

        #region 保存数据
        /// <summary>
        /// 保存数据
        /// </summary>
        /// <returns></returns>
        public int Save()
        {
            try
            {
                return DbContext.SaveChanges();
            }
            catch (DbEntityValidationException ex)
            {
                StringBuilder sbError = new StringBuilder();
                sbError.AppendLine("\n------------------- (DbEntityValidationException)详细错误信息如下 ---------------------");
                foreach (var validationResult in ex.EntityValidationErrors)
                {
                    if (validationResult.Entry.Entity != null)
                    {
                        sbError.AppendLine("当前对象详细内容:\n" + ObjectDumperHelper.Write(validationResult.Entry.Entity, 3));
                    }
                    foreach (var error in validationResult.ValidationErrors)
                    {
                        sbError.AppendFormat("PropertyName:{0} \t ErrorMessage:{1}\n", error.PropertyName, error.ErrorMessage);
                    }
                }
                Framework.Common.LogHelper.Error(sbError.ToString(), ex);
                return 0;
            }
            catch (Exception ex)
            {
                Framework.Common.LogHelper.Error("\n\n保存信息出错\n", ex);
                return 0;
            }
        }
        #endregion

        #region 事务
        /// <summary>
        /// 开始transaction
        /// </summary>
        /// <returns></returns>
        public IUnitOfWork TransactionStart()
        {
            unitOfWork = new GenericUnitOfWork();
            return unitOfWork;
        }
        /// <summary>
        /// 提交事务
        /// </summary>
        public void TransactionCommit()
        {
            unitOfWork.CommitTransaction();
        }

        #endregion

        #region DbContext
        /// <summary>
        /// DbContext
        /// </summary>
        public DbContext DbContext
        {
            get
            {
                return this._context;
            }
        }
        #endregion
    }
}
